package analiseSintatica.Regras.Expressoes;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSemantica.ErroSemantico;
import analiseSemantica.Tipos.TipoSemantico;
import analiseSemantica.Tipos.TiposSemanticos;
import analiseSemantica.estruturadedados.Identificador;
import analiseSemantica.estruturadedados.Token;
import analiseSintatica.AnalisadorSintatico;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Regra;

import java.util.LinkedList;

/**
 *
 * @author matheus
 * nathy
 */
public class RegraUnarioPrefixa extends Regra {

    protected static Regra instancia;

    protected String estrutura = "<unario_posfixa> | ('&' | '*') identificador";

    /**
     * Construtor privado necessario ao singleton
     */
    private RegraUnarioPrefixa() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraUnarioPrefixa getInstance() {
        if (instancia == null) {
            instancia = new RegraUnarioPrefixa();
        }
        return (RegraUnarioPrefixa) instancia;
    }

    @Override
    public TiposSemanticos analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

        TiposSemanticos tipoReturn = new TiposSemanticos();
        
        if (listaContem(RegraUnarioPosfixa.getInstance().getPrimeiro(), listaTokens.getFirst())) {

                tipoReturn = RegraUnarioPosfixa.getInstance().analisar(listaTokens);
            
        }else{

        	if(listaTokens.getFirst().getLexema().equals("&")){
        		reconheceToken(listaTokens, "&", estrutura);
        		LinkToken token = listaTokens.getFirst();
        		reconheceToken(listaTokens, "identificador", estrutura);
        		
        		Token id = AnalisadorSintatico.escopoatual.find(token.getLexema());
        		if(id == null || !(id instanceof Identificador)){
        			AnalisadorSintatico.errosemanticos.add(new ErroSemantico("Identificador "+token.getLexema()+" nao encontrado",token.getLinha()));
        			tipoReturn = null;
        		}else{
        			Identificador id2 = (Identificador)id;
        			tipoReturn.addTipos(new TipoSemantico("endereco."+id2.getTipo(), token.getLinha()));
        		
        		}
        	}else{
        		reconheceToken(listaTokens, "*", estrutura);
    			LinkToken token = listaTokens.getFirst();
    			reconheceToken(listaTokens, "identificador", estrutura);
    			
    			Token id = AnalisadorSintatico.escopoatual.find(token.getLexema());
        		if(id == null || !(id instanceof Identificador)){
        			AnalisadorSintatico.errosemanticos.add(new ErroSemantico("Identificador "+token.getLexema()+" nao encontrado",token.getLinha()));
        			tipoReturn = null;
        		}else{
        			Identificador id2 = (Identificador)id;
        			if(!id2.isPonteiro()){
        				AnalisadorSintatico.errosemanticos.add(new ErroSemantico("Identificador "+token.getLexema()+" nao e ponteiro",token.getLinha()));
        				tipoReturn = null;
        			}else
        				tipoReturn.addTipos(new TipoSemantico("ponteiro."+id2.getTipo(), token.getLinha()));
        		
        		}
        	}
        }
    			
        
        return tipoReturn;
    }



    protected void setPrimeiro() {
        primeiro = RegraUnarioPosfixa.getInstance().getPrimeiro();
        primeiro = getUniao(primeiro, RegraOpIncremento.getInstance().getPrimeiro());
    }
}
